<?php
/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
*/

/**
 * Description of RQLAutomatoState
 *
 * @author Admin
 */
class RQLAutomatoState {
    // Начальное состояние
    const START                 = 2;
    // Обрабатываем путь
    const PATH                  = 2;
    // обрабатываем якорь
    const ANCHOR                = 4;
    // обрабатываем ветки
    const BRANCHING             = 8;
    // обрабатываем изменение
    const SET                   = 16;

    // ожидания :)
    // ожидаем имя ноды
    const WAITING_NODE          = 32;
    const WAITING_DESDENDANT    = 64;
    const WAITING_DESCRIPTION   = 128;
    const WAITING_UPDATE        = 256;
    const WAITING_OPERATED_NODE = 512;

    const DONE                  = 2048;

    const ALL            = 126;

    private $position;
    private $state;
    /*
     * @type RQLPath
    */
    private $outcome;

    private $insert_query;
    private $update_query;
    private $select_query;
    private $delete_query;
    private $last_insertion = 0;

    function drop_operations_data() {
        $this->outcome->drop_operations_data();
    }

    public function __construct($state, $position = 0) {
        $this->state = $state;
        $this->position = $position;
        $this->outcome = new RQLPath();
    }

    public function __get($name) {
        if ($name == 'position') return $this->position;
        if ($name == 'state') return $this->state;
        if ($name == 'outcome') return $this->outcome;
        throw new Exception('Class RQLAutomatoState does not support property '.$name);
    }

    public function  __clone() {
        return new RQLAutomatoState($this->state, $this->position);
    }

    public function __set($name, $val) {
        if ($name == 'position') return $this->position = $val;
        if ($name == 'state') return $this->state = $val;
        if ($name == 'outcome') return $this->outcome = $val;
    }

    public function next() {
        return ++$this->position;
    }

    public function skip($val) {
        return $this->position += $val;
    }

    public function replace_state($old, $new) {
        $this->state ^= $old;
        $this->state |= $new;
        return $this->state;
    }


    public function add_outcome($node) {
        $this->outcome->add_node($node);
    }

    /**
     *
     * @return RQLNode
     */
    public function get_last_outcome() {
        return ($this->outcome->get_last_node());
    }

    public function set_last_outcome($val) {
        return ($this->outcome->set_last_node($val));
    }

    public function get_last_outcome_type() {
        return get_class($this->outcome->get_last_node());
    }

    public function get_real_name($alias) {
        for($i=0;$i<count($this->outcome);$i++) {
            $rn = $this->outcome[$i]->getRealName($alias);
            if ($rn !== false) return $rn;
        }

        return false;
    }

    public function getUpdate() {
        $res = array();
        for($i=0;$i<count($this->outcome);$i++) {
            $update = $this->outcome[$i]->getUpdate();
            if (count($update) > 0) {
                if (is_a($this->outcome[$i], 'RQLNode')) {
                    $res[$this->outcome[$i]->getName()] = $update;
                } else {
                    $res = array_merge($res, $update);
                }
            }
        }
        return $res;
    }

    public function get_next_insertion() {
        for($this->last_insertion; $this->last_insertion < count($this->outcome);$this->last_insertion++) {
            $outcome = $this->outcome[$this->last_insertion];
            if (is_a($outcome, 'RQLNode') && $outcome->operation == '+') {
                return $outcome->getName();
            } else {
                $sub_insertion = $outcome->get_next_insertion();
                if ($sub_insertion !== false) return $sub_insertion;
            }
        }
        return false;
    }

    public function get_node_path($name, $skip = 0) {
        $path = new RQLAutomatoState(self::DONE);
        $p = $this->outcome->get_node_path($name, $skip);
        $path->setOutcome($p);
        return $path;
        for($i=0;$i<count($this->outcome); $i++) {
            $outcome = $this->outcome[$i];
            if (is_a($outcome, 'RQLNode')) {
                $path->outcome[] = $outcome;
                if($outcome->getName() == $name) {
                    if ($skip == 0) return $path;
                    else $skip--;
                }
            } else {
                $sub_skip = 0;
                while(false !== ($sub_path = $outcome->get_node_path($name, $sub_skip++))) {
                    if ($skip == 0) {
                        $path->outcome = array_merge($path->outcome, $sub_path);
                        return $path;
                    } else $skip--;
                }
                $path->outcome[] = $outcome;
            }
        }
        return false;
    }

    public function setOutcome($out) {
        $this->outcome = $out;
    }

    public function drop_last_node() {
        return $this->outcome->grop_last_node();
    }
}
?>
